import 'package:web_socket_channel/io.dart';
import './socket_msg.dart';
import 'dart:convert';
import 'dart:async';
import '../user_proof.dart';

enum SocketListenerPage {
  lobby,
  room
}
class MySocket {
  static IOWebSocketChannel _socket;
  static Stream _socketStream;
  static StreamSink _socketSink;
  static Map<SocketListenerPage, Function> _listener = {};
  static List<ResMsgType> lobbyEventPage = [ResMsgType.invite, ResMsgType.updateMsgCount, ResMsgType.userInfo];

  static Timer _reconnectTimer;
  static int _connectCount = 0;
  static final int _reconnectInterval = 10;

  static Timer _heartTimer;
  static int _notResHeart = 0;
  static final Duration _heartInterval = Duration(seconds: 60);

  static void initSingleSocket() {
    if(_socket == null) {
      initConnection(reconnect: false);
    }
  }

  static void initConnection({bool reconnect=true}) {
    _connectCount ++;
    _socket = new IOWebSocketChannel.connect('ws://162.219.120.29:8082/ws?id='+UserProof.userId+(reconnect?'&type=1':''));//type：1:重连
      
    _socketStream = _socket.stream;
    _socketSink = _socket.sink;

    try {
      _socketSink.add('heart');

      _connectCount = 0;
      _notResHeart = 0;

      _socketStream.listen((data){
        resetHeartTimer();
        if(data == 'heart') {
          _notResHeart --;
        }else {
          data = json.decode(data);

          ResMsgType msgType = SocketMsg.resMsgTypeFromStr[data['type']];
          if(ResMsgType.userInfo == msgType) {
            UserProof.setUserInfo(data['data']['user_info']);
          }
          Function callback = _listener[lobbyEventPage.contains(msgType)?SocketListenerPage.lobby : SocketListenerPage.room];
          if(null != callback) {
            callback(data);
          }
        }
      });
      
      clearTimer(_reconnectTimer);
      resetHeartTimer();
    }catch(e) {
      if(_connectCount < 8) {
        clearTimer(_reconnectTimer);
        _reconnectTimer = Timer(Duration(seconds: _reconnectInterval * (_connectCount++)), (){
          initConnection();
        });
      }
    }
    
  }
  
  static void clearTimer(Timer timer) {
    if(null != timer && timer.isActive) {
      timer.cancel();
    }
  }
  static void resetHeartTimer() {
    clearTimer(_heartTimer);
    _heartTimer = Timer(_heartInterval, () {
      sendHeart();
      resetHeartTimer();
    });
  }
  static void sendHeart() {
    if(_notResHeart >= 2) {
      clearTimer(_heartTimer);
      initConnection();
    }else {
      _socketSink.add('heart');
      _notResHeart ++;
    }
  }
  static void sendMsg({SendMsgType type, Map data}) {
    _socketSink.add(SocketMsg(type: type, data: data).toString());
  }
  static void addListener({SocketListenerPage listenerPge, Function callback}) {
    if(_listener.containsKey(listenerPge)) {
      removeListener(listenerPge: listenerPge);
    }
    _listener[listenerPge] = callback;
  }
  static void removeListener({SocketListenerPage listenerPge}) {
    if(_listener.containsKey(listenerPge)) {
      _listener.remove(listenerPge);
    }
  }
}